#pragma once
#include <iostream>
#include <cstdint>
#include <functional>
#include <memory>
#include <vector>
#include <unordered_map>
#include <cassert>
#include<unistd.h>

// 定时任务类
// 定时触发任务
using OnTimerCallback = std::function<void()>;

// 定时清理任务
using ReleaseCallback = std::function<void()>;

class Timer
{
private:
    int _timeout;       // 定时器延迟
    bool _cancle;       // 任务取消
    uint64_t _timer_id; // 定时器id,用于判定任务的身份和唯一性

    OnTimerCallback _timer_callback;

    ReleaseCallback _release_callback;

public:
    Timer(int timeout, uint64_t timer_id) : _timeout(timeout), _timer_id(timer_id), _cancle(false) {}

    ~Timer()
    {
        // 根据相应条件执行相应的任务
        if (_release_callback)
            _release_callback();

        if (_timer_callback && !_cancle)
            _timer_callback();
    }

    uint64_t id();

    // 获取延时时间
    int Delay_time()
    {
        return _timeout;
    }

    // 取消任务
    void Cancle()
    {
        _cancle = true;
    }

    // 设置任务回调
    void Set_on_time_callback(const OnTimerCallback &cb)
    {
        _timer_callback = cb;
    }

    void Set_release_callback(const ReleaseCallback &cb)
    {
        _release_callback = cb;
    }
};

#define MAX_TIMEOUT 60

class TimerQueue
{

private:
    // 定义相应的结构
    using WeakTimer = std::weak_ptr<Timer>;
    using PtrTimer = std::shared_ptr<Timer>;

    // 时间轮的每一个节点都是vector,这样可以挂载更多任务
    using Buck = std::vector<PtrTimer>;
    using BuckList = std::vector<Buck>;

    // 定义相应的实例
    int _tick; // 时间轮指针，走到哪里就将哪里的vector进行clear，其中的PtrTimer进行释放

    int _capacity; // 最大容量，如果想要设计更大的时间，可以再设计一个具有六十个节点的分针定时器

    // 只有当PtrTimer的计数器真正为0,才会将其释放，执行Timer的析构函数，完成定时任务的执行

    BuckList _conns;

    // 保存定时任务对象的weak_ptr这样能在不影响shared_ptr计数器的同时，获取shared_ptr
    std::unordered_map<uint64_t, WeakTimer> _timers;

public:
    TimerQueue() : _tick(0),
                   _capacity(MAX_TIMEOUT),
                   _conns(_capacity)
    {
    }

    // 判断任务是否存在
    bool has_timer(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it != _timers.end())
        {
            return true;
        }

        return false;
    }

    // 添加一个任务
    void Timer_add(const OnTimerCallback &cb, int delay, uint64_t id)
    {
        // 只支持60s以内的任务
        if (delay > _capacity || delay <= 0)
            return;

        PtrTimer timer(new Timer(delay, id));

        // 设置定时任务
        timer->Set_on_time_callback(cb);

        timer->Set_release_callback(std::bind(&TimerQueue::Remove_weaktimer,this,id));

        // 添加相应的weak_ptr
        _timers[id] = WeakTimer(timer);

        // 将定时任务加入到时间轮数组
        _conns[(_tick + delay) % _capacity].push_back(timer);
    }

    // 根据id刷新定时任务
    void Timer_refresh(uint64_t id)
    {
        auto it = _timers.find(id);

        assert(it != _timers.end());

        // weak_ptr
        int delay = it->second.lock()->Delay_time();

        _conns[(_tick + delay) % _capacity].push_back(PtrTimer(it->second));
    }

    // 取消任务
    void timer_cancle(uint64_t id)
    {
        auto it = _timers.find(id);
        assert(it != _timers.end());

        PtrTimer pt = it->second.lock();

        if (pt)
            pt->Cancle();
    }

    // 设置给Timer，最终的任务执行完毕后从Timequeue移除timer信息
    void Remove_weaktimer(uint64_t id)
    {
        auto it = _timers.find(id);
        assert(it != _timers.end());

        _timers.erase(it);
    }

    // 清空对应位置的任务
    void run_ontime_task()
    {
        _tick = (_tick + 1) % _capacity;
        _conns[_tick].clear();
    }
};

class Timertest{

    private:
    int _data;

    public:
    Timertest(int data):_data(data){
        std::cout<<"test 构造"<<std::endl;
    }

    ~Timertest()
    {
        std::cout<<"test 析构"<<std::endl;
    }  
};



void del(Timertest *t)//释放相应的类
{
    delete t;
}

